// MatricesTransformation.cpp
// Implementation of Translation, Scaling, Rotation and Shearing

#include "MatricesLib.h"

#define PI 3.14159265

using namespace std;

namespace Matrices
{

	float matrix_t[4][4]; //transformation matrix
	float element_t[16]; //matrix_t to openGL mode
	int r = 4; //row
	int c = 4; //column


	///////////////////////////////////
	/* Create a Matrix for Translation
	   OpenGL: translate(tx,ty,tz);
	*/ 
	///////////////////////////////////
	float (*MyMatrices::TranslateMatrix(float tx, float ty, float tz))
	{
		//initialize the Matrix with row by column
		//matrix_t = new float*[r];
		//	for(int i = 0; i < r; i++)
		//	{ matrix_t[i] = new float[c]; }

		//create an identity matrix
		for(int i = 0; i < r; i++){ 
			for (int j = 0; j < c; j++){
				if(i == j)
					matrix_t[i][j] = 1;
				else 
					matrix_t[i][j] = 0;
			}
		}
		//translate
		matrix_t[r-1][0] = tx;
		matrix_t[r-1][1] = ty;
		matrix_t[r-1][2] = tz;

		int k = 0;
		for(int i = 0; i < r; i++){
			for(int j = 0; j < c; j++){
				element_t[k] = matrix_t[i][j];
				k++;
			}
		}

		return element_t;
	}


	////////////////////////////////
	/* Create a Matrix for Scale
	   OpenGL: scale(sx,sy,sz);
	*/
	////////////////////////////////
	float (*MyMatrices::ScaleMatrix(float sx, float sy, float sz))
	{
		//store elements
		for(int i = 0; i < r; i++){ 
			for (int j = 0; j < c; j++){
				if(i == j){
					if(i == 0)
						matrix_t[i][j] = sx;
					else if(i == 1)
						matrix_t[i][j] = sy;
					else if(i == 2)
						matrix_t[i][j] = sz;
					else
						matrix_t[i][j] = 1;
				}
				else 
					matrix_t[i][j] = 0;
			}
		}

		int k = 0;
		for(int i = 0; i < r; i++){
			for(int j = 0; j < c; j++){
				element_t[k] = matrix_t[i][j];
				k++;
			}
		}
		return element_t;
	}


	////////////////////////////////
	/* Create a Matrix for Rotation
	   OpenGL: rotate(angle, x, y, z);
	   if xyz = 0, rotate(angle, 1, 0, 0);
	   if xyz = 1, rotate(angle, 0, 1, 0);
	   if xyz = 2, rotate(angle, 0, 0, 1);
	*/
	////////////////////////////////
	float (*MyMatrices::RotateMatrix(int xyz, float angle))
	{
		//get the radian of an angle
		float radian = angle * PI / 180;
		//fill matrix with 0
		for(int i = 0; i < r; i++){ 
			for (int j = 0; j < c; j++){
				matrix_t[i][j] = 0;
			}
		}
		//rotation about the x-axis by angle
		if(xyz == 0)
		{
			matrix_t[0][0] = 1;
			matrix_t[1][1] = cos(radian);	
			matrix_t[2][2] = cos(radian);
			matrix_t[3][3] = 1;
			matrix_t[1][2] = sin(radian);
			matrix_t[2][1] = -sin(radian);
		}
		//rotation about the y-axis by angle
		if(xyz == 1)
		{
			matrix_t[0][0] = cos(radian);
			matrix_t[1][1] = 1;	
			matrix_t[2][2] = cos(radian);
			matrix_t[3][3] = 1;
			matrix_t[0][2] = -sin(radian);
			matrix_t[2][0] = sin(radian);
		}
		//rotation about the z-axis by angle
		if(xyz == 2)
		{
			matrix_t[0][0] = cos(radian);
			matrix_t[1][1] = cos(radian);	
			matrix_t[2][2] = 1;
			matrix_t[3][3] = 1;
			matrix_t[0][1] = sin(radian);
			matrix_t[1][0] = -sin(radian);		
		}
		
		int k = 0;
		for(int i = 0; i < r; i++){
			for(int j = 0; j < c; j++){
				element_t[k] = matrix_t[i][j];
				k++;
			}
		}
		return element_t;
	}

		
	////////////////////////////////
	/* Create a Matrix for Shearing
	   if xyz = 0, shear to the x axis;
	   if xyz = 1, shear to the y axis;
	   if xyz = 2, shear to the z axis;
	*/
	////////////////////////////////
	float (*MyMatrices::ShearMatrix(int xyz, float angle))
	{
		//create an identity matrix
		for(int i = 0; i < r; i++){ 
			for (int j = 0; j < c; j++){
				if(i == j)
					matrix_t[i][j] = 1;
				else 
					matrix_t[i][j] = 0;
			}
		}
		if(xyz == 0)
			matrix_t[0][1] = 1/tan(angle);
		if(xyz == 1)
			matrix_t[1][0] = 1/tan(angle);
		if(xyz == 2)
			matrix_t[2][0] = 1/tan(angle);
		
		int k = 0;
		for(int i = 0; i < r; i++){
			for(int j = 0; j < c; j++){
				element_t[k] = matrix_t[i][j];
				k++;
			}
		}
		return element_t;
	}

}